using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Drawing;
using System.Data;
using System.IO;
using System.Text;
using System.Windows.Forms;

using common = Microsoft.ConnectionEngine.Common;

namespace Microsoft.ConnectionEngine.SampleDeploymentManager.WizardPages
{
    public partial class ProgressPage : WizardPageBase
    {
        private const string SRC_FOLDER = "sourceFolder";
        private const string DEST_FOLDER = "destinationFolder";
        private const string SA_SUB_FOLDER = "saSubFolder";
        private const string SP_SUB_FOLDER = "spSubFolder";
        private const string SA_ENCRYPT_KEY_FOLDER = "saEncryptKeyFolder";
        private const string SA_CONFIG_FILE = "saConfigFile";
        private const string SP_CONFIG_FILE = "spConfigFile";

        private const string ROUTING_HOST = "routinghost";
        private const string CONN_ENG_USER = "connenguser";
        private const string CONN_ENG_PASS = "connengpass";

        private const string SPR_DB_HOST = "sprDBHost";
        private const string SPR_DB_NAME = "sprDBName";
        private const string SPR_DB_USER = "sprDBUser";
        private const string SPR_DB_PASS = "sprDBPass";

        private const string APP_IIS_SITE = "appIISSite";
        private const string APP_IIS_FOLDER = "appIISFolder";
        private const string APP_POOL_NAME = "appPoolName";
        private const string APP_POOL_USER = "appPoolUser";
        private const string APP_POOL_PASS = "appPoolPass";

        private const string SP_ID = "serviceProviderID";
        private const string SPR_PUBLIC_KEY = "sprPublicKey";
        private const string PUBLIC_KEY = "publicKey";
        
        #region defaults
        private const string DB_DATA_CREATE_FILE_NAME = "SPR-DB-CreateData.sql";
        private const string DB_DATA_DESTROY_FILE_NAME = "SPR-DB-Destroy.sql";

        private const string PUBLIC_KEY_FILE_NAME = "SAPublicKey.xml";
        private const string PRIVATE_KEY_FILE_NAME = "SAPrivateKey.xml";
        private const string SPR_PUBLIC_KEY_FILE_NAME = "SPRPublicKey.xml";
        private const string DEFAULT_APP_POOL_NAME = "ConnectionEngineAppPool";
        #endregion

        public ProgressPage()
        {
            InitializeComponent();
        }

        public override void Activate(ref Dictionary<string, object> parameters)
        {
            base.Activate(ref parameters);

            DoOperation();
        }

        private void DoOperation()
        {
            try
            {
                Init();
                this.barProgress.Value += 14;
                Application.DoEvents();

                Step1();
                this.barProgress.Value += 14;
                Application.DoEvents();

                Step2();
                this.barProgress.Value += 14;
                Application.DoEvents();

                Step3();
                this.barProgress.Value += 14;
                Application.DoEvents();

                Step4();
                this.barProgress.Value += 14;
                Application.DoEvents();

                Step5();
                this.barProgress.Value += 14;
                Application.DoEvents();

                Step6();
                this.barProgress.Value = 100;
                Application.DoEvents();

                this.OnComplete();
            }
            catch (Exception ex)
            {
                RollBack();
                this.OnError(ex.Message);
            }
        }

        private void Init()
        {
            //Ensure that all the parameters are valid
            DirectoryInfo destinationFolder = new DirectoryInfo(_parameters[DEST_FOLDER].ToString());
            string saSubFolder = _parameters[SA_SUB_FOLDER].ToString();
            string saEncryptKeySubFolder = _parameters[SA_ENCRYPT_KEY_FOLDER].ToString();

            if (saEncryptKeySubFolder.Length > 0)
            {
                if (!Path.IsPathRooted(saEncryptKeySubFolder))
                {
                    saEncryptKeySubFolder = Path.Combine(destinationFolder.FullName, saEncryptKeySubFolder);
                }

                if (!saEncryptKeySubFolder.EndsWith("\\")) saEncryptKeySubFolder += "\\";
            }
            else
            {
                saEncryptKeySubFolder = destinationFolder.FullName;
            }

            if (_parameters.ContainsKey(SA_ENCRYPT_KEY_FOLDER)) _parameters.Remove(SA_ENCRYPT_KEY_FOLDER);
            _parameters.Add(SA_ENCRYPT_KEY_FOLDER, saEncryptKeySubFolder);

            string saConfigFile = _parameters[SA_CONFIG_FILE].ToString();

            saConfigFile = Path.Combine(destinationFolder.FullName, saConfigFile);

            if (_parameters.ContainsKey(SA_CONFIG_FILE)) _parameters.Remove(SA_CONFIG_FILE);
            _parameters.Add(SA_CONFIG_FILE, saConfigFile);

            string spConfigFile = _parameters[SP_CONFIG_FILE].ToString();

            spConfigFile = Path.Combine(destinationFolder.FullName, spConfigFile);

            if (_parameters.ContainsKey(SP_CONFIG_FILE)) _parameters.Remove(SP_CONFIG_FILE);
            _parameters.Add(SP_CONFIG_FILE, spConfigFile);

            if (_parameters.ContainsKey(APP_IIS_FOLDER)) _parameters.Remove(APP_IIS_FOLDER);
            _parameters.Add(APP_IIS_FOLDER, Path.Combine(destinationFolder.FullName, saSubFolder));
        }

        private void Step1()
        {
            //Copy the source implementation to the destination
            DirectoryInfo sourceFolder = new DirectoryInfo(_parameters[SRC_FOLDER].ToString());
            DirectoryInfo destinationFolder = new DirectoryInfo(_parameters[DEST_FOLDER].ToString());

            Utilities.XCopy(sourceFolder, destinationFolder);
        }

        private void Step2()
        {
            //Generate the public and private keys
            FileInfo fileInfo;
            DirectoryInfo saEncryptKeyFolder = new DirectoryInfo(_parameters[SA_ENCRYPT_KEY_FOLDER].ToString());
            if (!saEncryptKeyFolder.Exists) saEncryptKeyFolder.Create();

            common.Crypto.RSAKeyCreator kc = new Microsoft.ConnectionEngine.Common.Crypto.RSAKeyCreator();
            string publicKey = kc.PublicKeyXml;
            string privateKey = kc.PrivateKeyXml;

            fileInfo = new FileInfo(Path.Combine(saEncryptKeyFolder.FullName, PUBLIC_KEY_FILE_NAME));
            Utilities.SaveDataToFile(fileInfo.FullName, publicKey);

            fileInfo = new FileInfo(Path.Combine(saEncryptKeyFolder.FullName, PRIVATE_KEY_FILE_NAME));
            Utilities.SaveDataToFile(fileInfo.FullName, privateKey);

            if (_parameters.ContainsKey(PUBLIC_KEY)) _parameters.Remove(PUBLIC_KEY);
            _parameters.Add(PUBLIC_KEY, publicKey);
        }

        private void Step3()
        {
            //Get the public key for the service provider register
            FileInfo fileInfo;
            DirectoryInfo saEncryptKeyFolder = new DirectoryInfo(_parameters[SA_ENCRYPT_KEY_FOLDER].ToString());
            if (!saEncryptKeyFolder.Exists) saEncryptKeyFolder.Create();

            string dbServer = _parameters[SPR_DB_HOST].ToString();
            string dbName = _parameters[SPR_DB_NAME].ToString();
            string dbUser = _parameters[SPR_DB_USER].ToString();
            string dbPass = _parameters[SPR_DB_PASS].ToString();

            if ((string.Compare(dbServer, ".") == 0) ||
                (string.Compare(dbServer, "localhost", true) == 0))
            {
                dbServer = Utilities.GetCurrentHostName();
            }

            string sprPublicKey = Utilities.GetServiceProviderPublicKey(dbServer, dbName, dbUser, dbPass, 101);

            fileInfo = new FileInfo(Path.Combine(saEncryptKeyFolder.FullName, SPR_PUBLIC_KEY_FILE_NAME));
            Utilities.SaveDataToFile(fileInfo.FullName, sprPublicKey);

            if (_parameters.ContainsKey(SPR_PUBLIC_KEY)) _parameters.Remove(SPR_PUBLIC_KEY);
            _parameters.Add(SPR_PUBLIC_KEY, sprPublicKey);
        }

        private void Step4()
        {
            //Update the deployed system adapter config file
            DirectoryInfo destinationFolder = new DirectoryInfo(_parameters[DEST_FOLDER].ToString());
            destinationFolder = new DirectoryInfo(Path.Combine(destinationFolder.FullName, "IncomingFolder"));

            string spID = _parameters[SP_ID].ToString();
            string routingHost = _parameters[ROUTING_HOST].ToString();
            string connEngUser = _parameters[CONN_ENG_USER].ToString();
            string connEngPass = _parameters[CONN_ENG_PASS].ToString();

            if (!destinationFolder.Exists) destinationFolder.Create();
            FileInfo fileInfo = new FileInfo(_parameters[SA_CONFIG_FILE].ToString());

            Dictionary<string, string> fileParameters = new Dictionary<string, string>();

            fileParameters.Add("[spid]", spID);
            fileParameters.Add("[routinghost]", routingHost);
            fileParameters.Add("[connenguser]", connEngUser);
            fileParameters.Add("[connengpass]", connEngPass);
            fileParameters.Add("[incomingfolder]", destinationFolder.FullName);

            Utilities.SetFileParameters(fileInfo.FullName, fileParameters);
        }

        private void Step5()
        {
            //Update the deployed service provider config file
            FileInfo fileInfo = new FileInfo(_parameters[SP_CONFIG_FILE].ToString());
            string appName = _parameters[APP_IIS_SITE].ToString();

            Dictionary<string, string> fileParameters = new Dictionary<string, string>();

            fileParameters.Add("[sawshost]", Utilities.GetCurrentHostName());
            fileParameters.Add("[sawssite]", appName);

            Utilities.SetFileParameters(fileInfo.FullName, fileParameters);
        }

        private void Step6()
        {
            DirectoryInfo appIISFolder = new DirectoryInfo(_parameters[APP_IIS_FOLDER].ToString());
            string appName = _parameters[APP_IIS_SITE].ToString();
            string appPoolName = _parameters[APP_POOL_NAME].ToString();
            string appPoolUsername = _parameters[APP_POOL_USER].ToString();
            string appPoolPassword = _parameters[APP_POOL_PASS].ToString();

            if (appPoolName.Length == 0)
            {
                appPoolName = DEFAULT_APP_POOL_NAME;
            }

            Utilities.CreateIISVirtualDir(Utilities.GetCurrentHostName(), appName, appIISFolder.FullName, appPoolName, appPoolUsername, appPoolPassword);
        }

        private void RollBack()
        {
            DirectoryInfo destinationFolder = new DirectoryInfo(_parameters[DEST_FOLDER].ToString());
            string appName = _parameters[APP_IIS_SITE].ToString();
            string appPoolName = _parameters[APP_POOL_NAME].ToString();

            Utilities.RemoveIISVirtualDir(Utilities.GetCurrentHostName(), appName, appPoolName);

            if (destinationFolder.Exists) destinationFolder.Delete(true);
        }
    }
}
